/* #include "../include/analysisCommand.h" */
#include "../include/threadPool.h"
#include <mysql/mysql.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/sendfile.h>
#include <sys/mman.h>
typedef struct train_s{
    int type;
    int length;
    char data[1000];
}train_t;

int recvn(int sockfd,void *buf,int length){
    int total=0;
    char * p=(char *)buf;
    while(total<length){
        int ret=recv(sockfd,p+total,length-total,0);
        total+=ret;
    }
    return 0;
}
int get_store_path(char buf[])
{
    strcpy(buf,"/home/");
    uid_t uid = getuid();
    struct passwd *pwd = getpwuid(uid);
    strcat(buf,pwd->pw_name);
    strcat(buf,"/serverStore/");
    if(access(buf,F_OK) != 0)
    {
        mkdir(buf,0777);
    }
    /* printf("%s\n",buf); */
    return 0;
}

int recvup_mysql_select(const char *name,const char *condition1,const char *condition2,char * tempbuf){
    bzero(tempbuf,strlen(tempbuf));//用来装 查找到的结果的字符串

    MYSQL *mysql= mysql_init(NULL);   //申请空间
    MYSQL *res=mysql_real_connect(mysql,   //链接数据库
                                  "localhost",
                                  "root",
                                  "123",
                                  "test",
                                  0,NULL,0);
    if(res==NULL){       //判断数据库链接
        fprintf(stderr,"%s\n",mysql_error(mysql));
        exit(-1);
    }
    char buf[4096]={0};      //用来存储select命令
    sprintf(buf,"select %s from file  where %s = '%s';",name,condition1,condition2);
    /* printf("%s\n",buf); */
    int sret=mysql_query(mysql,buf);
    if(sret==-1){
        return sret;//查表失败
    }
    MYSQL_RES *table= mysql_store_result(mysql);
    if(mysql_num_rows(table)==0){
        return -1;
    }
    char buf1[4096]={0};       //用来存储查找到的数据结果
    for(unsigned int  i=0;i<mysql_num_rows(table);i++){
        MYSQL_ROW row=mysql_fetch_row(table);
        for(unsigned int j=0;j<mysql_num_fields(table);j++){
            strcat(buf1,row[j]);
        }
    }
    /* printf("这里测试一下：%s\n",buf1); */
    strcpy(tempbuf,buf1);//将查找到的数据返回给tempbuf，好让他带回去！
    return 0;
}
int s_download(int netfd,commandStack_t *pcommandStack){
    /* printf("-------\n"); */
    // 数据库连接
    threadPool_t threadPool;
    pthread_mutex_lock(&threadPool.mutex);
    MYSQL *mysql=mysql_init(NULL);
    mysql_real_connect(mysql,"localhost","root","123","test",0,NULL,0);
    pthread_mutex_unlock(&threadPool.mutex);

    // 求绝对路径
    char path[1024] = {0};
    get_store_path(path);
        
    train_t train;
    recvn(netfd,&train.type,sizeof(train.type));

    if(train.type==11){
        // 执行断点续传逻辑
        // 收文件名
        char filename[1024]={0};
        recvn(netfd,&train.type,sizeof(train.type));
        recvn(netfd,&train.length,sizeof(train.length));
        recvn(netfd,train.data,train.length);
        /* printf("train.length=%d\n",train.length); */
        memcpy(filename,train.data,train.length);
        /* printf("filename=%s\n",filename); */

        // 收断点文件大小
        int size=0;
        recvn(netfd,&train.type,sizeof(train.type));
        recvn(netfd,&train.length,sizeof(train.length));
        recvn(netfd,train.data,train.length);
        memcpy(&size,train.data,train.length);
        printf("size=%d\n",size);

        // 算实际文件大小
        /* strcat(path,"/"); */
        strcat(path,filename);
        struct stat statbuf;                                             
        /* stat(filename,&statbuf); */
        stat(path,&statbuf);
        int filesize=statbuf.st_size;
        /* printf("filesize=%d\n",filesize); */
        train.type=0;
        train.length=sizeof(filesize);
        memcpy(train.data,&filesize,train.length);
        send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(netfd,&filesize,train.length,MSG_NOSIGNAL);
 

        // 从断点处开始发文件
        /* printf("11path=%s\n",path); */
        int fd=open(path,O_RDWR);
        lseek(fd,size,SEEK_SET);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                int ret=read(fd,train.data,sizeof(train.data));
                /* if(ret==0) break; */
                train.length=ret;
                train.type=0;
                send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
                send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL); 
                send(netfd,train.data,train.length,MSG_NOSIGNAL);
                if(ret==0) break;
            }
        }else{
            printf("我是mmap\n");
            sendfile(netfd,fd,NULL,filesize-size);
            printf("发完了\n");
        }
        close(fd);
        return 0;
    }else if(train.type==22){
        // 执行正常逻辑
        // 收文件名
        char filename[1024]={0};
        recvn(netfd,&train.type,sizeof(train.type));
        recvn(netfd,&train.length,sizeof(train.length));
        recvn(netfd,train.data,train.length);
        memcpy(filename,train.data,train.length);
        printf("filename=%s\n",filename);

        //得到用户当前的工作路径
        char path_buf[512];
        char cid[5]={0};
        sprintf(cid,"%d",pcommandStack->num[pcommandStack->top]);
        mysql_use_select("path","id",cid,path_buf,pcommandStack);

        strcat(path_buf,filename);
        /* printf("path_buf:%s\n",path_buf); */
        char hash[1000]={0};
        recvup_mysql_select("haxi","path",path_buf,hash);
        // 算实际文件大小+发给对面
        /* strcat(path,"/"); */
        
        strcat(path,hash);

        struct stat statbuf;
        /* stat(filename,&statbuf); */
        stat(path,&statbuf);
        /* printf("22path=%s\n",path); */
        int filesize=statbuf.st_size;
        printf("filesize=%d\n",filesize);
        train.type=0;
        train.length=sizeof(filesize);
        memcpy(train.data,&filesize,train.length);
        send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(netfd,train.data,train.length,MSG_NOSIGNAL);

        // 发文件
        /* strcat(path,filename); */
        /* printf("33path=%s\n",path); */

        int fd=open(path,O_RDWR);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                int ret=read(fd,train.data,sizeof(train.data));
                /* if(ret==0) break; */
                train.length=ret;
                train.type=0;
                send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
                send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL); 
                send(netfd,train.data,train.length,MSG_NOSIGNAL);
                if(ret==0) break;
            }
        }else{
            printf("我是mmap\n");
            sendfile(netfd,fd,NULL,filesize);
            printf("发完了\n");

        }
        close(fd);
        return 0;
    }
    return 0;
}

int s_recv_up(int netfd,commandStack_t *pcommandStack){
    train_t train;
    MYSQL *mysql=mysql_init(NULL);
    mysql_real_connect(mysql,"localhost","root","123","test",0,NULL,0);
    /* pthread_mutex_unlock(&threadPool.mutex); */

    // 求绝对路径
    char path[1024]={0};
    get_store_path(path);

    int pirentId=pcommandStack->num[pcommandStack->top];
    
    // 收文件名
    recvn(netfd,&train.type,sizeof(train.type));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    char filename[1024]={0};
    memcpy(filename,train.data,train.length);
    printf("filename=%s\n",filename);
    char path2[1024]={0};
    strcpy(path2,path);
    strcat(path2,filename);
    printf("1path=%s\n",path2);
    // 收hash
    recvn(netfd,&train.type,sizeof(train.type));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    char hash[1024]={0};
    memcpy(hash,train.data,train.length);
    /* printf("hash=%s\n",hash); */
    
    // 判断数据库表里边有一样的哈希吗，并给c发一个flag
    char sql2[2048]="select * from file;";
    sprintf(sql2,"select id from file where haxi = '%s';",hash);
    /* printf("sql2=%s\n",sql2); */
    mysql_query(mysql,sql2);
    MYSQL_RES *table1=mysql_store_result(mysql);
    // 判断数据库表里边有一样的哈希吗，并给c发一个flag                   
    int flag=0;
    
    if(table1 != NULL && mysql_num_rows(table1) > 0)
    {
        printf("找到了相同文件\n");
        flag = 1;
    }
      
    printf("flag=%d\n",flag); 


    // 发flag给对面
    train.type=0;
    train.length=sizeof(flag);
    memcpy(train.data,&flag,train.length);
    send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
    send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
    send(netfd,train.data,train.length,MSG_NOSIGNAL);
    /* printf("%s\n",path); */
    if(flag==1){
        printf("触发了秒传！\n");
        printf("准备往表里插入数据\n");
        char *username=pcommandStack->username;
        int parent_id=pirentId;
        char path1[100];
        get_curpath(pcommandStack,path1);
        if(strlen(path1) > 1)
        {
            strcat(path1,"/");
        }
        strcat(path1,filename);
        printf("path1=%s\n",path1);
        // 插入一行数据
        /* char sql1[]="insert into file (filename,username,parent_id,path1,type,hash) values ('file1','zs', 1,'/file1','f','123');"; */
        char sql1[4096]={0};
        sprintf(sql1,"insert into file \
                (filename,username,parent_id,path,type,haxi) \
                values ('%s','%s', %d,'%s','f','%s');",filename,username,parent_id,path1,hash);
        mysql_query(mysql,sql1);
        printf("插入数据成功\n");
        return 0;
    }

    /* strcat(path,"/");  // 注意 */
    int size=0;
    printf("path=%s\n",path);
    char path5[1024]={0};
    strcpy(path5,path);
    strcat(path5,hash);
    if(access(path5,F_OK)==0){
        printf("断点续传\n");
        train.type=11;
        send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);

        // 发断点文件大小
        struct stat statbuf;
        printf("filename=%s\n",filename);
        stat(path,&statbuf);
        size=statbuf.st_size;
        printf("size=%d\n",size);
        train.type=0;
        train.length=sizeof(size);
        printf("train.lenght=%d\n",train.length);
        memcpy(train.data,&size,train.length);
        printf("train.data=%s\n",train.data);
        memcpy(train.data,&size,sizeof(size));
        send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(netfd,train.data,train.length,MSG_NOSIGNAL);

        // 收实际文件大小
        int filesize=0;
        recvn(netfd,&train.type,sizeof(train.type));
        recvn(netfd,&train.length,sizeof(train.length));
        recvn(netfd,train.data,train.length);
        memcpy(&filesize,train.data,train.length);
        printf("filesize=%d\n",filesize);

        
        // 收文件
        char path3[1024]={0};
        strcpy(path3,path);
        strcat(path3,hash);
        int fd=open(path3,O_RDWR|O_CREAT|O_APPEND,0666);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                /* if(train.length==0) break; */
                recvn(netfd,&train.type,sizeof(train.type));
                recvn(netfd,&train.length,sizeof(train.length));
                /* if(train.length==0) break; */
                recvn(netfd,train.data,train.length);
                if(train.length==0) break;
                write(fd,train.data,train.length);
            }
        }else{
            printf("我是mmap\n");
            ftruncate(fd,filesize);
            char *p=(char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
            recvn(netfd,p+size,filesize-size);
            /* write(fd,p,filesize-size); */
            munmap(p,filesize);
            printf("收完了\n");
        }
        
    }else{
        train.type=22;
        send(netfd,&train.type,sizeof(train.type),MSG_NOSIGNAL);

        // 收实际文件大小
        int filesize=0;
        recvn(netfd,&train.type,sizeof(train.type));
        recvn(netfd,&train.length,sizeof(train.length));
        recvn(netfd,train.data,train.length);
        memcpy(&filesize,train.data,train.length);
        printf("filesize=%d\n",filesize);


        // 正常收文件
        printf("正常收文件\n");
        char path4[1024]={0};
        strcpy(path4,path);
        strcat(path4,hash);
        int fd=open(path4,O_RDWR|O_CREAT|O_TRUNC,0666);
        /* strcpy(temp_path,filename); */
        /* int fd=open(path,O_RDWR|O_CREAT|O_TRUNC,0666); */
        printf("3path = %s\n", path);
        if(filesize<10){
            while(1){
                bzero(train.data,sizeof(train.data));
                /* if(train.length==0) break; */
                recvn(netfd,&train.type,sizeof(train.type));
                recvn(netfd,&train.length,sizeof(train.length));
                if(train.length==0) break;
                recvn(netfd,train.data,train.length);
                write(fd,train.data,train.length);
            }
        }else{
            printf("我是mmap\n");
            ftruncate(fd,filesize);
            char *p=(char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
            recvn(netfd,p,filesize);
            /* write(sockfd,p,filesize); */
            munmap(p,filesize);
            printf("收完了\n");

        }
    }
    
    printf("准备往表里插入数据\n");
    char *username=pcommandStack->username;
    int parent_id=pirentId;
    char path1[100];
    get_curpath(pcommandStack,path1);
    if(strlen(path1) > 1)
    {
        strcat(path1,"/");
    }
    strcat(path1,filename);
    printf("path1=%s\n",path1);
    // 插入一行数据
    /* char sql1[]="insert into file (filename,username,parent_id,path1,type,hash) values ('file1','zs', 1,'/file1','f','123');"; */
    char sql1[4096]={0};
    sprintf(sql1,"insert into file (filename,username,parent_id,path,type,haxi)values ('%s','%s', %d,'%s','f','%s');",filename,username,parent_id,path1,hash);
    mysql_query(mysql,sql1);
    printf("插入数据成功\n");

    return 0;
}


